// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/media_router/cast_dialog_metrics.h"

#include "base/metrics/histogram_macros.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/media_router/ui_media_sink.h"
#include "chrome/common/pref_names.h"
#include "components/media_router/common/mojom/media_route_provider_id.mojom-shared.h"
#include "components/media_router/common/pref_names.h"
#include "components/prefs/pref_service.h"

namespace media_router {

using mojom::MediaRouteProviderId;

namespace {

DialogActivationLocationAndCastMode GetActivationLocationAndCastMode(
    MediaRouterDialogOpenOrigin activation_location,
    MediaCastMode cast_mode,
    bool is_icon_pinned) {
  switch (activation_location) {
    case MediaRouterDialogOpenOrigin::TOOLBAR:
      if (is_icon_pinned) {
        switch (cast_mode) {
          case MediaCastMode::PRESENTATION:
            return DialogActivationLocationAndCastMode::
                kPinnedIconAndPresentation;
          case MediaCastMode::TAB_MIRROR:
            return DialogActivationLocationAndCastMode::kPinnedIconAndTabMirror;
          case MediaCastMode::DESKTOP_MIRROR:
            return DialogActivationLocationAndCastMode::
                kPinnedIconAndDesktopMirror;
        }
      } else {
        switch (cast_mode) {
          case MediaCastMode::PRESENTATION:
            return DialogActivationLocationAndCastMode::
                kEphemeralIconAndPresentation;
          case MediaCastMode::TAB_MIRROR:
            return DialogActivationLocationAndCastMode::
                kEphemeralIconAndTabMirror;
          case MediaCastMode::DESKTOP_MIRROR:
            return DialogActivationLocationAndCastMode::
                kEphemeralIconAndDesktopMirror;
        }
      }
      break;
    case MediaRouterDialogOpenOrigin::CONTEXTUAL_MENU:
      switch (cast_mode) {
        case MediaCastMode::PRESENTATION:
          return DialogActivationLocationAndCastMode::
              kContextMenuAndPresentation;
        case MediaCastMode::TAB_MIRROR:
          return DialogActivationLocationAndCastMode::kContextMenuAndTabMirror;
        case MediaCastMode::DESKTOP_MIRROR:
          return DialogActivationLocationAndCastMode::
              kContextMenuAndDesktopMirror;
      }
      break;
    case MediaRouterDialogOpenOrigin::PAGE:
      switch (cast_mode) {
        case MediaCastMode::PRESENTATION:
          return DialogActivationLocationAndCastMode::kPageAndPresentation;
        case MediaCastMode::TAB_MIRROR:
          return DialogActivationLocationAndCastMode::kPageAndTabMirror;
        case MediaCastMode::DESKTOP_MIRROR:
          return DialogActivationLocationAndCastMode::kPageAndDesktopMirror;
      }
      break;
    case MediaRouterDialogOpenOrigin::APP_MENU:
      switch (cast_mode) {
        case MediaCastMode::PRESENTATION:
          return DialogActivationLocationAndCastMode::kAppMenuAndPresentation;
        case MediaCastMode::TAB_MIRROR:
          return DialogActivationLocationAndCastMode::kAppMenuAndTabMirror;
        case MediaCastMode::DESKTOP_MIRROR:
          return DialogActivationLocationAndCastMode::kAppMenuAndDesktopMirror;
      }
      break;
    // |OVERFLOW_MENU| refers to extension icons hidden in the app menu. That
    // mode is no longer available for the Cast toolbar icon.
    case MediaRouterDialogOpenOrigin::OVERFLOW_MENU:
    case MediaRouterDialogOpenOrigin::SYSTEM_TRAY:
    case MediaRouterDialogOpenOrigin::TOTAL_COUNT:
      break;
  }
  NOTREACHED();
  return DialogActivationLocationAndCastMode::kMaxValue;
}

}  // namespace

CastDialogMetrics::CastDialogMetrics(
    const base::Time& initialization_time,
    MediaRouterDialogOpenOrigin activation_location,
    Profile* profile)
    : initialization_time_(initialization_time),
      activation_location_(activation_location),
      is_icon_pinned_(
          profile->GetPrefs()->GetBoolean(::prefs::kShowCastIconInToolbar)) {
  MediaRouterMetrics::RecordIconStateAtDialogOpen(is_icon_pinned_);
  MediaRouterMetrics::RecordCloudPrefAtDialogOpen(
      profile->GetPrefs()->GetBoolean(prefs::kMediaRouterEnableCloudServices));
}

CastDialogMetrics::~CastDialogMetrics() = default;

void CastDialogMetrics::OnSinksLoaded(const base::Time& sinks_load_time) {
  if (!sinks_load_time_.is_null())
    return;
  MediaRouterMetrics::RecordMediaRouterDialogLoaded(sinks_load_time -
                                                    initialization_time_);
  sinks_load_time_ = sinks_load_time;
}

void CastDialogMetrics::OnPaint(const base::Time& paint_time) {
  if (!paint_time_.is_null())
    return;
  MediaRouterMetrics::RecordMediaRouterDialogPaint(paint_time -
                                                   initialization_time_);
  paint_time_ = paint_time;
}

void CastDialogMetrics::OnStartCasting(const base::Time& start_time,
                                       int selected_sink_index,
                                       MediaCastMode cast_mode,
                                       SinkIconType icon_type,
                                       bool has_cast_and_dial) {
  DCHECK(!sinks_load_time_.is_null());
  MediaRouterMetrics::RecordStartRouteDeviceIndex(selected_sink_index);
  if (!first_action_recorded_) {
    MediaRouterMetrics::RecordStartLocalSessionLatency(start_time -
                                                       sinks_load_time_);
  }
  MaybeRecordFirstAction(MediaRouterUserAction::START_LOCAL);
  MaybeRecordActivationLocationAndCastMode(cast_mode);
  MediaRouterMetrics::RecordMediaSinkTypeForCastDialog(icon_type);
  if (has_cast_and_dial) {
    MediaRouterMetrics::RecordMediaSinkTypeWhenCastAndDialPresent(
        icon_type, UiType::kCastDialog);
  }
}

void CastDialogMetrics::OnStopCasting(bool is_local_route) {
  if (is_local_route) {
    MediaRouterMetrics::RecordStopLocalRoute();
    MaybeRecordFirstAction(MediaRouterUserAction::STOP_LOCAL);
  } else {
    MediaRouterMetrics::RecordStopRemoteRoute();
    MaybeRecordFirstAction(MediaRouterUserAction::STOP_REMOTE);
  }
}

void CastDialogMetrics::OnCastModeSelected() {
  MaybeRecordFirstAction(MediaRouterUserAction::CHANGE_MODE);
}

void CastDialogMetrics::OnCloseDialog(const base::Time& close_time) {
  if (!first_action_recorded_ && !paint_time_.is_null())
    MediaRouterMetrics::RecordCloseDialogLatency(close_time - paint_time_);
  MaybeRecordFirstAction(MediaRouterUserAction::CLOSE);
}

void CastDialogMetrics::OnRecordSinkCount(
    const std::vector<CastDialogSinkButton*>& sink_buttons) {
  media_router::MediaRouterMetrics::RecordDeviceCount(sink_buttons.size());

  std::map<MediaRouteProviderId, std::map<bool, int>> counts = {
      {MediaRouteProviderId::CAST, {{true, 0}, {false, 0}}},
      {MediaRouteProviderId::DIAL, {{true, 0}, {false, 0}}},
      {MediaRouteProviderId::WIRED_DISPLAY, {{true, 0}, {false, 0}}}};
  for (const CastDialogSinkButton* sink_button : sink_buttons) {
    if (sink_button->sink().provider != MediaRouteProviderId::TEST) {
      counts.at(sink_button->sink().provider).at(sink_button->GetEnabled())++;
    }
  }
  for (auto provider : {MediaRouteProviderId::CAST, MediaRouteProviderId::DIAL,
                        MediaRouteProviderId::WIRED_DISPLAY}) {
    for (bool is_available : {true, false}) {
      int count = counts.at(provider).at(is_available);
      media_router::MediaRouterMetrics::RecordCastDialogDeviceCount(
          activation_location_, provider, is_available, count);
    }
  }
}

void CastDialogMetrics::MaybeRecordFirstAction(MediaRouterUserAction action) {
  if (first_action_recorded_)
    return;
  MediaRouterMetrics::RecordMediaRouterInitialUserAction(action);
  first_action_recorded_ = true;
}

void CastDialogMetrics::MaybeRecordActivationLocationAndCastMode(
    MediaCastMode cast_mode) {
  if (activation_location_and_cast_mode_recorded_)
    return;
  UMA_HISTOGRAM_ENUMERATION(
      "MediaRouter.Ui.Dialog.ActivationLocationAndCastMode",
      GetActivationLocationAndCastMode(activation_location_, cast_mode,
                                       is_icon_pinned_));
  activation_location_and_cast_mode_recorded_ = true;
}

}  // namespace media_router
